// Copyright 2017, James Sarrett.
// Copyright 2017, Bastiaan Olij.
// SPDX-License-Identifier: BSL-1.0
/*
 * OpenHMD - Free and Open Source API and drivers for immersive technology.
 */

/* Shaders */


#include "shaders.h"

const char * const distortion_vert =
"#version 120\n"
"void main(void)\n"
"{\n"
    "gl_TexCoord[0] = gl_MultiTexCoord0;\n"
    "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n"
"}";

const char * const distortion_frag =
"#version 120\n"
"\n"
"//per eye texture to warp for lens distortion\n"
"uniform sampler2D warpTexture;\n"
"\n"
"//Position of lens center in m (usually eye_w/2, eye_h/2)\n"
"uniform vec2 LensCenter;\n"
"//Scale from texture co-ords to m (usually eye_w, eye_h)\n"
"uniform vec2 ViewportScale;\n"
"//Distortion overall scale in m (usually ~eye_w/2)\n"
"uniform float WarpScale;\n"
"//Distoriton coefficients (PanoTools model) [a,b,c,d]\n"
"uniform vec4 HmdWarpParam;\n"
"\n"
"//chromatic distortion post scaling\n"
"uniform vec3 aberr;\n"
"\n"
"void main()\n"
"{\n"
    "//output_loc is the fragment location on screen from [0,1]x[0,1]\n"
    "vec2 output_loc = vec2(gl_TexCoord[0].s, gl_TexCoord[0].t);\n"
    "//Compute fragment location in lens-centered coordinates at world scale\n"
	"vec2 r = output_loc * ViewportScale - LensCenter;\n"
    "//scale for distortion model\n"
    "//distortion model has r=1 being the largest circle inscribed (e.g. eye_w/2)\n"
    "r /= WarpScale;\n"
"\n"
    "//|r|**2\n"
    "float r_mag = length(r);\n"
    "//offset for which fragment is sourced\n"
    "vec2 r_displaced = r * (HmdWarpParam.w + HmdWarpParam.z * r_mag +\n"
    "HmdWarpParam.y * r_mag * r_mag +\n"
    "HmdWarpParam.x * r_mag * r_mag * r_mag);\n"
    "//back to world scale\n"
    "r_displaced *= WarpScale;\n"
    "//back to viewport co-ord\n"
    "vec2 tc_r = (LensCenter + aberr.r * r_displaced) / ViewportScale;\n"
    "vec2 tc_g = (LensCenter + aberr.g * r_displaced) / ViewportScale;\n"
    "vec2 tc_b = (LensCenter + aberr.b * r_displaced) / ViewportScale;\n"
"\n"
    "float red = texture2D(warpTexture, tc_r).r;\n"
    "float green = texture2D(warpTexture, tc_g).g;\n"
    "float blue = texture2D(warpTexture, tc_b).b;\n"
    "//Black edges off the texture\n"
    "gl_FragColor = ((tc_g.x < 0.0) || (tc_g.x > 1.0) || (tc_g.y < 0.0) || (tc_g.y > 1.0)) ? vec4(0.0, 0.0, 0.0, 1.0) : vec4(red, green, blue, 1.0);\n"
"}";

const char *const distortion_vert_330 =
"#version 330\n"
"\n"
"layout (location=0) in vec2 coords;"
"uniform mat4 mvp;"
"out vec2 T;"
"\n"
"void main(void)\n"
"{\n"
    "T = coords;\n"
    "gl_Position = mvp * vec4(coords, 0.0, 1.0);\n"
"}";

const char *const distortion_frag_330 =
"#version 330\n"
"\n"
"//per eye texture to warp for lens distortion\n"
"uniform sampler2D warpTexture;\n"
"\n"
"//Position of lens center in m (usually eye_w/2, eye_h/2)\n"
"uniform vec2 LensCenter;\n"
"//Scale from texture co-ords to m (usually eye_w, eye_h)\n"
"uniform vec2 ViewportScale;\n"
"//Distortion overall scale in m (usually ~eye_w/2)\n"
"uniform float WarpScale;\n"
"//Distoriton coefficients (PanoTools model) [a,b,c,d]\n"
"uniform vec4 HmdWarpParam;\n"
"\n"
"//chromatic distortion post scaling\n"
"uniform vec3 aberr;\n"
"\n"
"in vec2 T;\n"
"out vec4 color;\n"
"\n"
"void main()\n"
"{\n"
    "//output_loc is the fragment location on screen from [0,1]x[0,1]\n"
    "vec2 output_loc = vec2(T.s, T.t);\n"
    "//Compute fragment location in lens-centered coordinates at world scale\n"
    "vec2 r = output_loc * ViewportScale - LensCenter;\n"
    "//scale for distortion model\n"
    "//distortion model has r=1 being the largest circle inscribed (e.g. eye_w/2)\n"
    "r /= WarpScale;\n"
    "\n"
    "//|r|**2\n"
    "float r_mag = length(r);\n"
    "//offset for which fragment is sourced\n"
    "vec2 r_displaced = r * (HmdWarpParam.w + HmdWarpParam.z * r_mag +\n"
    "HmdWarpParam.y * r_mag * r_mag +\n"
    "HmdWarpParam.x * r_mag * r_mag * r_mag);\n"
    "//back to world scale\n"
    "r_displaced *= WarpScale;\n"
    "//back to viewport co-ord\n"
    "vec2 tc_r = (LensCenter + aberr.r * r_displaced) / ViewportScale;\n"
    "vec2 tc_g = (LensCenter + aberr.g * r_displaced) / ViewportScale;\n"
    "vec2 tc_b = (LensCenter + aberr.b * r_displaced) / ViewportScale;\n"
"\n"
    "float red = texture(warpTexture, tc_r).r;\n"
    "float green = texture(warpTexture, tc_g).g;\n"
    "float blue = texture(warpTexture, tc_b).b;\n"
    "//Black edges off the texture\n"
    "color = ((tc_g.x < 0.0) || (tc_g.x > 1.0) || (tc_g.y < 0.0) || (tc_g.y > 1.0)) ? vec4(0.0, 0.0, 0.0, 1.0) : vec4(red, green, blue, 1.0);\n"
"}";

const char * const distortion_vert_es =
"#version 100\n"
"\n"
"attribute vec2 coords;"
"uniform mat4 mvp;"
"varying vec2 T;"
"void main(void)\n"
"{\n"
	"T = coords;\n"
	"gl_Position = mvp * vec4(coords, 0.0, 1.0);\n"
"}";

const char * const distortion_frag_es =
"#version 100\n"
"precision mediump float;"
"\n"
"varying vec2 T;"
"//per eye texture to warp for lens distortion\n"
"uniform sampler2D warpTexture;\n"
"\n"
"//Position of lens center in m (usually eye_w/2, eye_h/2)\n"
"uniform vec2 LensCenter;\n"
"//Scale from texture co-ords to m (usually eye_w, eye_h)\n"
"uniform vec2 ViewportScale;\n"
"//Distortion overall scale in m (usually ~eye_w/2)\n"
"uniform float WarpScale;\n"
"//Distoriton coefficients (PanoTools model) [a,b,c,d]\n"
"uniform vec4 HmdWarpParam;\n"
"\n"
"//chromatic distortion post scaling\n"
"uniform vec3 aberr;\n"
"\n"
"void main()\n"
"{\n"
	"//output_loc is the fragment location on screen from [0,1]x[0,1]\n"
	"vec2 output_loc = vec2(T.s, T.t);\n"
	"//Compute fragment location in lens-centered coordinates at world scale\n"
	"vec2 r = output_loc * ViewportScale - LensCenter;\n"
	"//scale for distortion model\n"
	"//distortion model has r=1 being the largest circle inscribed (e.g. eye_w/2)\n"
	"r /= WarpScale;\n"
"\n"
	"//|r|**2\n"
	"float r_mag = length(r);\n"
	"//offset for which fragment is sourced\n"
	"vec2 r_displaced = r * (HmdWarpParam.w + HmdWarpParam.z * r_mag +\n"
	"HmdWarpParam.y * r_mag * r_mag +\n"
	"HmdWarpParam.x * r_mag * r_mag * r_mag);\n"
	"//back to world scale\n"
	"r_displaced *= WarpScale;\n"
	"//back to viewport co-ord\n"
	"vec2 tc_r = (LensCenter + aberr.r * r_displaced) / ViewportScale;\n"
	"vec2 tc_g = (LensCenter + aberr.g * r_displaced) / ViewportScale;\n"
	"vec2 tc_b = (LensCenter + aberr.b * r_displaced) / ViewportScale;\n"
"\n"
	"float red = texture2D(warpTexture, tc_r).r;\n"
	"float green = texture2D(warpTexture, tc_g).g;\n"
	"float blue = texture2D(warpTexture, tc_b).b;\n"
	"//Black edges off the texture\n"
	"gl_FragColor = ((tc_g.x < 0.0) || (tc_g.x > 1.0) || (tc_g.y < 0.0) || (tc_g.y > 1.0)) ? vec4(0.0, 0.0, 0.0, 1.0) : vec4(red, green, blue, 1.0);\n"
"}";
